A naive Common Lisp implementation of the [[https://automerge.org/docs/how-it-works/runtime/][Automerge runtime protocol]], using the [[https://code.briarproject.org/briar/briar-spec/blob/master/protocols/BSP.md#423-eager-mode][Bramble Sync Protocol's "Eager mode"]] for the underlying message passing instead of the normal Automerge sync protocol. Intended for educational purposes.

* Demo:

Initialize two users, `Alice` and `Bob`.

#+BEGIN_SRC common-lisp
(defvar *alice* (create-schema))
(defvar *bob* (create-schema))
#+END_SRC

Exchange contact ID info: 

#+BEGIN_SRC common-lisp
(add-contact *alice* "bob" (getf *bob* :id))
(add-contact *bob* "alice" (getf *alice* :id))
#+END_SRC

Now let's say Alice adds a key value pair, then updates it:

#+BEGIN_SRC common-lisp
(put-msg *alice* (list 0 (getf *alice* :id)) "food" "pizza")
(put-msg *alice* (list 0 (getf *alice* :id)) "food" "tofu")
#+END_SRC

Alice can now create an outgoing report of messages for Bob:

#+BEGIN_SRC common-lisp
(send-eager-update *alice* (getf *bob* :id))
#+END_SRC

in this case, the report looks like this:

#+BEGIN_SRC common-lisp
((5 2)
(0 NIL)
 (1
  (:OPID (2 7926) :OBJID (0 7926) :PROP "food" :ACTION "set value" :VALUE
   "tofu" :DEP ((1 7926))))
 (1
  (:OPID (1 7926) :OBJID (0 7926) :PROP "food" :ACTION "set value" :VALUE
   "pizza" :DEP NIL)))
#+END_SRC

- Report with a leading number of `5` corresponds to the custom lamport clock report.
- The rest of the reports use the flags described in the [[https://code.briarproject.org/briar/briar-spec/blob/master/protocols/BSP.md][BSP Documentation]].

Bob can process this report to recieve the updates Alice made:
  
#+BEGIN_SRC common-lisp
(process-eager-update *bob* (getf *alice* :id)
		      (send-eager-update *alice* (getf *bob* :id)))
#+END_SRC

Now that Alice and Bob's states are synced, we can try and create a merge conflict:

#+BEGIN_SRC common-lisp
;;;; Create a merge conflict
(put-msg *bob* (list 0 (getf *alice* :id)) "food" "salad")
(put-msg *alice* (list 0 (getf *alice* :id)) "food" "pasta")
#+END_SRC

Now the state's of both trees are diverged, let's reconcile them now using a two-way sync.

#+BEGIN_SRC common-lisp
;;;; TWO WAY SYNC
;;;; note that order does not matter
(process-eager-update *alice*
		      (getf *bob* :id)
		      (send-eager-update *bob* (getf *alice* :id)))
(process-eager-update *bob*
		      (getf *alice* :id)
		      (send-eager-update *alice* (getf *bob* :id)))
#+END_SRC

Thanks to the Automerge runtime protocol which uses "Last Writer Wins" + using Contact ID as the tiebreaker, we can see that both structures show the same value of "salad" for the "food" key.

#+BEGIN_SRC common-lisp
;;;; Should both return "salad"
(get-msg *alice* (list 0 (getf *alice* :id)) "food")
(get-msg *bob* (list 0 (getf *alice* :id)) "food")
#+END_SRC


*** Nesting Objects

You can also set a key to point to another Map object

#+BEGIN_SRC common-lisp
;;;; Put objects into slots
(let ((table (put-obj *bob* (list 0 (getf *alice* :id)) "contact")))
  (put-msg *bob* table "email" "someemail@email.com"))
(let ((table (get-msg *bob* (list 0 (getf *alice* :id)) "contact")))
  (get-msg *bob* table "email")) ; "someemail@email.com
#+END_SRC
